package com.rtx.edi.platform.baseinfo.service.impl;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.ibatis.javassist.CtClass;
import org.apache.ibatis.javassist.NotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rtx.api.annotation.DataSourceAnnotation;
import com.rtx.common.ClassDescJsonStr;
import com.rtx.common.JavassistHelp;
import com.rtx.edi.model.apibaseinfo.po.PlApibaseinfo;
import com.rtx.edi.platform.baseinfo.bean.ApiStdRequest;
import com.rtx.edi.platform.baseinfo.mapper.PlApiStdRequestMapper;
import com.rtx.edi.platform.baseinfo.mapper.PlApibaseinfoMapper;
import com.rtx.edi.platform.baseinfo.service.PlApiStdRequestService;
import com.rtx.wms.std.ctclass.ClassHolder;

import cn.hutool.core.lang.UUID;

@SuppressWarnings("all")
@Service
public class PlApiStdRequestServiceImpl extends ServiceImpl<PlApiStdRequestMapper,ApiStdRequest>implements PlApiStdRequestService{

	Logger log = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	PlApibaseinfoMapper plApibaseinfoMapper;
	
	@DataSourceAnnotation
	@Override
	public List<ApiStdRequest> selectList(String datasourceky, LambdaQueryWrapper<ApiStdRequest> qw) {
		return baseMapper.selectList(qw);
	}

	@DataSourceAnnotation
	@Override
	public void selectList(Page<ApiStdRequest> pageParam, ApiStdRequest po) {
        LambdaQueryWrapper<ApiStdRequest> query = Wrappers.lambdaQuery();
        query.eq(ApiStdRequest::getApiid, po.getApiid());
        query.like(po.getFieldname() != null,ApiStdRequest::getFieldname, po.getFieldname());
        query.like(po.getFielddesc() != null,ApiStdRequest::getFielddesc, po.getFielddesc());
        query.eq(po.getActiveclass() != null,ApiStdRequest::getActiveclass, po.getActiveclass());
        baseMapper.selectPage(pageParam,query);
	}
	
	

	@DataSourceAnnotation
	@Override
	public void addApiStdRequest(String datasourckey, ApiStdRequest dto) {
		//校验字段是否已经存在
		checkField(dto);
		
		baseMapper.insert(dto);
	}
	
	private void checkField(ApiStdRequest dto) {
		LambdaQueryWrapper<ApiStdRequest> query = Wrappers.lambdaQuery();
		query.eq(ApiStdRequest::getApiid, dto.getApiid());
		query.eq(ApiStdRequest::getActiveclass, dto.getActiveclass());
		query.eq(ApiStdRequest::getFieldname, dto.getFieldname());
		boolean exists = baseMapper.exists(query);
		Assert.isTrue(!exists,dto.getFieldname()+"字段已存在不能重复添加");
	}
	
	@Override
	public void activeFieldAddCache(Long apiid) {
		try {
			LambdaQueryWrapper<ApiStdRequest> query = Wrappers.lambdaQuery();
			query.eq(ApiStdRequest::getApiid, apiid);
			
			List<ApiStdRequest> list = baseMapper.selectList(query);
			
			
			PlApibaseinfo api =	plApibaseinfoMapper.selectById(apiid);
			
			Map<String,Class> ctConfig = ClassHolder.apiconfigClassMap.get(apiid+"");
			
			if(ctConfig == null) {
				ctConfig = new HashMap<String,Class>();
			}
			
			Map<String,List<ApiStdRequest>> groupByMap = list.stream().collect(Collectors.groupingBy(ApiStdRequest::getActiveclass));
			
			for(String classNameAndLikclassName:groupByMap.keySet()) {
				//获取数组第一个className为主类
				String className = classNameAndLikclassName.split(",")[0];
				//将要添加的属性
				List<ApiStdRequest> addColumns = groupByMap.get(classNameAndLikclassName);
				
				CtClass ctclass =	JavassistHelp.pool.makeClass(className+"-"+UUID.randomUUID());
				CtClass ctSuppclass = JavassistHelp.pool.get(className);
				ctclass.setSuperclass(ctSuppclass);
				
				//添加属性值
				for(ApiStdRequest config:addColumns) {
					JavassistHelp.addFieldAndAddGetSetMethod(ctclass, config.getFieldname());
				}
				
				if(classNameAndLikclassName.equals(api.getMainclass())) {
					ctConfig.put("main", ctclass.toClass());
					//判断是否拼接了关联的类 假如存在用逗号分割的其值 ,改值大于1则认为存在拼接的情况
					int linkCount = api.getMainclass().split(",").length;
					//添加关联class 比如 api_orders 类关联 orders类
					if(api.getMainclass().startsWith(className)&& linkCount >1) {
						String linkClassName = classNameAndLikclassName.split(",")[1];
						//创建关联类
						Class linkClass =	createLinkClass(linkClassName,addColumns); 
						//将关联类写入缓存中
						ctConfig.put("main_link", linkClass);
					}
				}else if(classNameAndLikclassName.equals(api.getSubclass())) {
					//判断是否拼接了关联的类 假如存在用逗号分割的其值 ,改值大于1则认为存在拼接的情况
					int linkCount = api.getSubclass().split(",").length;
					ctConfig.put("sub", ctclass.toClass());
					if(api.getSubclass().startsWith(className)&& linkCount >1) {
						String linkClassName = classNameAndLikclassName.split(",")[1];
						//创建关联类
						Class linkClass = createLinkClass(linkClassName,addColumns); 
						//将关联类写入缓存中
						ctConfig.put("sub_link", linkClass);
					}
				}else {
					
				}
			}
			
			ClassHolder.apiconfigClassMap.put(apiid+"", ctConfig);
			
			JSONObject root = new JSONObject();

			
			//表头json
			//获取数组第一个className为主类
			String mainClassName = api.getMainclass().split(",")[0];
			ClassDescJsonStr.getSTDRequest(mainClassName,null,root,new HashSet<>());
			for(ApiStdRequest head:groupByMap.get(api.getMainclass())) {
				root.put(head.getFieldname(), "");
			}
			
			if(StringUtils.hasLength(api.getSubclass())) {
				
				//获取数组第一个className为主类
				String subClassName = api.getSubclass().split(",")[0];
				//明细json
				JSONObject detail = new JSONObject();
				ClassDescJsonStr.getSTDRequest(subClassName,null,detail,new HashSet<>());
				for(ApiStdRequest d:groupByMap.get(api.getSubclass())) {
					detail.put(d.getFieldname(), "");
				}
				JSONArray details = new JSONArray();
				details.add(detail);
				root.put("details", details);
			}

			
			ClassHolder.supperClassDyJSON.put(api.getMainclass(), root.toJSONString());
			
			LambdaUpdateWrapper<PlApibaseinfo> upd = Wrappers.lambdaUpdate();
			upd.eq(PlApibaseinfo::getId, apiid);
			upd.set(PlApibaseinfo::getApiRequestTemplate, root.toJSONString());
			plApibaseinfoMapper.update(null, upd);
		} catch (Exception e) {
			log.error("",e);
		}
	}
	
	//动态创建类
	private Class createLinkClass(String className,List<ApiStdRequest> externFieldList) throws Exception {
		CtClass ctclass =	JavassistHelp.pool.makeClass(className+"-"+UUID.randomUUID());
		CtClass ctSuppclass = JavassistHelp.pool.get(className);
		ctclass.setSuperclass(ctSuppclass);
		
		//添加属性值
		for(ApiStdRequest config:externFieldList) {
			JavassistHelp.addFieldAndAddGetSetMethod(ctclass, config.getFieldname());
		}
		
		return ctclass.toClass();
	}
	
	public void loadCtClass() {
		List<PlApibaseinfo> list =  plApibaseinfoMapper.selectList(Wrappers.lambdaQuery());
		for(PlApibaseinfo api:list) {
			LambdaQueryWrapper<ApiStdRequest> qw = Wrappers.lambdaQuery();
			qw.eq(ApiStdRequest::getApiid, api.getId());
			boolean exists = baseMapper.exists(qw);
			if(exists) {
				activeFieldAddCache(api.getId());
			}
		}
	}
	
//	public String compareSqlField(Long apiId) {
//        LambdaQueryWrapper<ApiStdRequest> query = Wrappers.lambdaQuery();
//        query.eq(ApiStdRequest::getApiid, apiId);
//		return null;
//	}
}
